class Selector
  attr_accessor :calcultion, :initial_machine, :current_machine_population

  def initialize(calc = nil, initial_machine = nil)
    @calculation = calc
    @initial_machine = initial_machine
  end

  def run_selection(iterations = 1000, opts = {})
    num_keep = opts[:num_kept_machines] || 5
    population_size = opts[:population_size] || 10

    @current_machine_population ||= [@initial_machine]

    1.upto(population_size - 1) do |idx|
      @current_machine_population[idx] = @initial_machine.dup.mutate
    end

    1.upto(iterations) do 
      results = @current_machine_population.map do |machine|
        [@calculation.run_calculation(machine), machine]
      end

      puts "Fitness Values: #{results.map{|x| x[0]}.inspect}"

      results = results.sort{|a, b| a[0] <=> b[0] || -1}  #The ||-1 is to correct for NaN's
      current_organism_idx = 0
      #NOTE - need to randomize in some way
      while(current_organism_idx < population_size) do
        0.upto(num_keep - 1) do |keep_idx|
          if results[keep_idx][0] == 0
            @current_machine_population[current_organism_idx] = results[keep_idx][1].dup
          else
            @current_machine_population[current_organism_idx] = results[keep_idx][1].dup.mutate
          end
          current_organism_idx = current_organism_idx + 1
        end
      end
    end
  end
end
